package me.evis.mobile.sms2cal;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import me.evis.mobile.sms2cal.model.SmsData;
import me.evis.mobile.sms2cal.parser.CanonicalParseRule;
import me.evis.mobile.sms2cal.parser.GenericCanonicalSmsParser;
import me.evis.mobile.sms2cal.parser.NLPTimeParser;
import me.evis.mobile.sms2cal.parser.SmsParser;
import me.evis.mobile.sms2cal.provider.CanonicalParseRuleContentProvider;

import org.json.JSONException;

import android.app.Service;
import android.content.Intent;
import android.database.Cursor;
import android.os.IBinder;
import android.util.Log;

public class SmsParseService extends Service {
    public static final String PARSER_THREAD_NAME = "me.evis.mobile.sms2cal.PARSER_THREAD";
    
    /** Tag string for our debug logs */
    private static final String TAG = "me.evis.mobile.sms2cal.SmsParseService";
    
    private SmsBatchParser batchParser;
    private List<SmsParser> parsers;
    
	/* (non-Javadoc)
	 * @see android.app.Service#onCreate()
	 */
	@Override
    public void onCreate() {
	    Log.d(TAG, "Initializing SmsParseService");
	    
	    batchParser = new SmsBatchParser(this);
	    parsers = new ArrayList<SmsParser>();
	    
	    // 1. GenericCanonicalSmsParser
	    Cursor c = getContentResolver().query(CanonicalParseRuleContentProvider.CONTENT_URI, 
	            null, null, null, null);
        Map<Integer, String> seqToRuleMap = new HashMap<Integer, String>();
        while (c.moveToNext()) {
            boolean enabled = c.getInt(c.getColumnIndex(CanonicalParseRuleContentProvider.ENABLED)) != 0;
            int sequence = c.getInt(c.getColumnIndex(CanonicalParseRuleContentProvider.SEQUENCE));
            String ruleJson = c.getString(c.getColumnIndex(CanonicalParseRuleContentProvider.RULE_JSON));
            
            if (enabled) {
                // Also record sequence
                seqToRuleMap.put(sequence, ruleJson);
            }
        }
        c.close();
        
        try {
            if (!seqToRuleMap.isEmpty()) {
                List<CanonicalParseRule> rules = new ArrayList<CanonicalParseRule>();
                // Sort by sequence
                List<Integer> seqs = new LinkedList<Integer>(seqToRuleMap.keySet());
                Collections.sort(seqs);
                for (Iterator<Integer> iter = seqs.iterator(); iter.hasNext();) {
                    Integer seq = iter.next();
                    rules.add(CanonicalParseRule.fromJSON(seqToRuleMap.get(seq)));
                }
                parsers.add(new GenericCanonicalSmsParser(rules));
                Log.d(TAG, "Added GenericCanonicalSmsParser with " + rules.size() + " rules");
            }
        } catch (JSONException e) {
            Log.e(TAG, "Error initializing Canonical Parser rules. ", e);
        }
        
        // 2. NLPTimeParser
        try {
            parsers.add(new NLPTimeParser(this));
            Log.d(TAG, "Added NLPTimeParser");
        } catch (IOException e) {
            Log.e(TAG, "Error loading NLP Parser models. ", e);
        }
	}

    /* (non-Javadoc)
     * @see android.app.Service#onStart(Intent,int)
     * For pre-2.0 platforms
     */
    @Override
	public void onStart(Intent intent, int startId) {
	    handleCommand(intent);
	}

	/* (non-Javadoc)
	 * @see android.app.Service#onStartCommand(android.content.Intent, int, int)
	 */
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
	    handleCommand(intent);
	    // We want this service to continue running until it is explicitly
	    // stopped, so return sticky.
	    return START_STICKY;
	}
	
	protected void handleCommand(Intent intent){
	    @SuppressWarnings("unchecked")
        List<SmsData> smsDatas = 
            (List<SmsData>) intent.getExtras().get(SmsReceiver.SMS_DATA_EXTRA);
	    Log.d(TAG, "Parsing " + smsDatas.size() + " SMS data");
	    batchParser.parseSmsData(smsDatas, parsers);
//	    new Thread(new Runnable() {
//            @Override
//            public void run() {
//                new SmsBatchParser(context).parseSmsData(smsDatas);
//            }
//        }, PARSER_THREAD_NAME).start();
	}

	/* (non-Javadoc)
     * @see android.app.Service#onBind(Intent)
     */
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
